import os
import sys
import threading
import time  # 时间操作
from datetime import datetime

import requests
import winsound
from bs4 import BeautifulSoup  #
from selenium import webdriver  # 浏览器
from selenium.common.exceptions import UnexpectedAlertPresentException, NoSuchElementException, \
    StaleElementReferenceException, ElementNotInteractableException, \
    ElementClickInterceptedException, NoSuchWindowException, InvalidArgumentException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
import socket


def getHostIp():
    """
    查询本机ip地址
    :return:
    """
    global s
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 80))
        ip = s.getsockname()[0]
    finally:
        s.close()
    return ip


baseRefUrl = "http://182.92.68.170:8086/api/v3"
# 浏览器设置
dirPath = "C:\\Users\\" + os.getlogin() + "\\AppData\\Local\\Google\\Chrome\\User Data"
options = webdriver.ChromeOptions()
options.add_argument('--disable-software-rasterizer')
options.add_experimental_option("excludeSwitches", ['enable-automation', 'enable-logging'])
options.add_argument('--ignore-certificate-errors')
options.add_argument(r"user-data-dir=" + dirPath)
# 设置中文
options.add_argument('lang=zh_CN.UTF-8')
# 去掉受自动化测试软件提示
options.add_experimental_option('useAutomationExtension', False)
# 更换头部
ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36'
options.add_argument('user-agent="%s"' % ua)
isExists = os.path.exists(dirPath)
if not isExists:
    os.makedirs(dirPath)


# driver = webdriver.Chrome("C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe",chrome_options=options)
class DoctorAutomate:
    def __init__(self,version):
        self.dogFlag = 1
        self.version = version
        self.userIp = None
        self.username = None
        self.driver = None
        self.orderStatus = 0
        self.index = 0
        self.url = "https://table-web.ybdoctor.com/order"
        self.workUrl = "https://table-web.ybdoctor.com/work"
        self.saveLogPath = "D://automateLogs"
        self.current_time=time.strftime('%Y-%m-%d',time.localtime(time.time()))  # 返回当前时间

    def start(self):
        global startBtn
        self.log("—-— 启动" + self.version + "版本 go go go———")
        winsound.Beep(400, 900)
        # 接单
        self.startChrome()
        self.log("开始启动子线程")
        threading.Thread(target=self.closeTipsWindow).start()
        self.log("启动电子狗")
        # 多线程电子狗 定时器 检查页面是否停顿，程序是否崩溃。
        threading.Thread(target=self.startEdog).start()
        self.log("子线程启动完成")
        self.log("获取左侧菜单列表")
        tempIndexOf = 1
        while True:
            try:
                tempIndexOf = tempIndexOf + 1
                if tempIndexOf > 20:
                    break
                menuItems = driver.find_elements(By.CLASS_NAME, "ant-menu-item")
                self.log("点击工作台")
                menuItems[1].click()
                break
            except Exception:
                continue
        self.confirmDialog(driver)
        # 读取当前登录的用户信息。
        self.userIp = getHostIp()
        self.username = driver.find_element(By.XPATH,
                                            ".//*[@class='ant-avatar avatar___2IGyD ant-avatar-circle ant-avatar-image']/following-sibling::span").text
        self.log("开始刷新抢单。。。")
        while True:
            try:
                bs = BeautifulSoup(driver.page_source, 'lxml')
                menuItem = bs.find_all('li', class_="ant-menu-item-selected")[0]
                # 需要等一下，直到页面加载完成
                if menuItem.find("span").text == "工作台":
                    self.confirmDialog(driver)
                if menuItem.find("span").text == "订单池":
                    # try:
                    #     closeBtn = driver.find_element(By.CSS_SELECTOR,'button[class="ant-modal-close"]')
                    #     closeBtn.click()
                    # except (NoSuchElementException,UnexpectedAlertPresentException,ElementNotInteractableException):
                    #     self.log("2不处理~")
                    try:
                        startBtns = driver.find_elements(By.CLASS_NAME, "ant-btn")
                        btnFlag = True;
                        for item in startBtns:
                            # self.log(item.text)
                            if (item.text == '开始接诊'):
                                startBtn = item
                            if (item.text == '暂停接诊'):
                                btnFlag = False
                        if btnFlag:
                            self.log("点击开始接诊。。。")
                            startBtn.click()
                    except (ElementClickInterceptedException, UnexpectedAlertPresentException):
                        self.log("获取接诊按钮异常，跳过~")
                    tbody = driver.find_element(By.CLASS_NAME, "ant-table-tbody")
                    if (tbody is None) or (tbody.get_attribute("innerHTML") is ''):
                        btns = driver.find_elements(By.CLASS_NAME, "ant-btn")
                        for btn in btns:
                            if btn.text == '刷新':
                                btn.click()
                                self.dogFlag = self.dogFlag + 1
                    else:
                        # 接单
                        self.accept(driver)
            except (StaleElementReferenceException, UnexpectedAlertPresentException, NoSuchElementException,
                    ElementClickInterceptedException, NameError, ElementNotInteractableException, AttributeError,
                    NoSuchWindowException):
                self.log("弹窗导致的异常，不处理异常，跳过 ~")
            except Exception as e:
                self.log("抛出特殊异常,并重启浏览器 ==>")
                import traceback
                traceback.print_exc()
                winsound.Beep(400, 900)
                self.log("==============================>")
                self.start()

    # 重启
    def startChrome(self):
        global driver
        self.log("正在启动浏览器...")
        while True:
            try:
                os.system('taskkill /F /IM chrome.exe')
                driver = webdriver.Chrome("./chromedriver.exe", options=options)
                break
            except InvalidArgumentException:
                continue
        driver.get(self.url)
        self.driver = driver
        self.log("启动浏览器成功...")
        wait = WebDriverWait(driver, 10000, 0.5)
        wait.until(lambda diver: driver.find_element(By.XPATH,
                                                     ".//*[@class='ant-avatar avatar___2IGyD ant-avatar-circle ant-avatar-image']/following-sibling::span"))

    # 接单
    def accept(self, driver):
        acceptBtn = driver.find_element(By.CLASS_NAME, "ant-btn-background-ghost")
        # 打开确认窗口
        acceptBtn.click()
        self.log("捕获了新处方单")
        self.orderStatus = 1
        # wait = WebDriverWait(driver, 10000, 0.5)
        # wait.until(lambda diver: driver.find_element(By.CLASS_NAME,'preButton___2lN1Q'))
        # tipBtns = driver.find_elements_by_class_name("ant-btn ant-btn-primary ant-btn-sm")
        # for tipBtn in tipBtns:
        #     if tipBtn.text == '知道了':
        #         tipBtn.click();
        self.confirmDialog(driver)

    # 关闭弹窗
    def closeTipsWindow(self):
        while True:
            if self.orderStatus == 1:
                self.log("订单已被抢了。")
                self.orderStatus = 0

            try:
                closeBtn = driver.find_element(By.XPATH,
                                               "//div[@class='ant-modal-footer']/div/button[@class='ant-btn ant-btn-primary']")
                closeBtn.click()
            except Exception:
                self.orderStatus = 0
            try:
                closeBtns = driver.find_elements(By.XPATH, "//*[text()='确 定']")
                for btn in closeBtns:
                    btn.click()
            except Exception:
                self.orderStatus = 0
            try:
                btns = driver.find_elements(By.CSS_SELECTOR, 'button[class="ant-btn ant-btn-primary"]')
                for btn in btns:
                    if "知道了" in btn.text:
                        btn.click()
            except Exception:
                self.orderStatus = 0
            try:
                closeBtns = driver.find_elements(By.CLASS_NAME, 'ant-modal-close')
                for btn in closeBtns:
                    btn.click()
            except Exception:
                self.orderStatus = 0
            try:
                closeBtn = driver.find_element(By.CSS_SELECTOR, 'div[class="ant-tooltip-inner"] > a')
                closeBtn.click()
            except Exception:
                self.orderStatus = 0
            try:
                closeBtn = driver.find_element(By.CLASS_NAME, 'ant-notification-notice-close')
                closeBtn.click()
            except Exception:
                self.orderStatus = 0
            time.sleep(2)

    # 处理处方单
    def confirmDialog(self, driver):
        time.sleep(6)
        self.log("开始检查工作台是否有处方单。")
        try:
            okBtn = driver.find_element(By.CLASS_NAME, "preButton___2lN1Q")
            okBtn.click()
        except  (NoSuchElementException, ElementClickInterceptedException):
            self.log("工作台没有处方单，返回到订单池~")
            # menuItems = driver.find_elements_by_xpath("//li//a")
            try:
                menuItems = driver.find_elements(By.CLASS_NAME, "ant-menu-item")
                menuItems[0].click()
            except Exception:
                import traceback
                traceback.print_exc()
                print("===============找不到菜单==================")

                winsound.Beep(400, 900)
            return
        # 以下报错通知管理员，不重启   10分钟超时 判断1分钟是否处理了
        # bs = BeautifulSoup(driver.page_source,'lxml')
        try:
            start = time.process_time()
            self.log("工作台有处方单，开始点击确认按钮。")
            # self.getAndSaveData(driver)
            notSuccess = True
            while notSuccess:
                self.dogFlag = self.dogFlag + 1
                try:
                    end = time.process_time()
                    if end - start > 35:
                        winsound.Beep(400, 900)
                        self.sendMessage("订单未处理超时，还有未处理的单子，立即通知管理员", driver.page_source)
                    tipBtns = driver.find_elements(By.XPATH, ".//*[@class='ant-btn ant-btn-primary ant-btn-sm']")
                    for tipBtn in tipBtns:
                        self.log(str(tipBtn.text) + "======132行")
                        if (tipBtn.text.replace(' ', '')) == ("确 定".replace(' ', '')):
                            tipBtn.click()
                    self.index = self.index + 1
                    self.log("===============处理了" + str(self.index) + "单=====================")
                    notSuccess = False
                except (NoSuchElementException, ElementClickInterceptedException):
                    continue
        except Exception:
            import traceback
            traceback.print_exc()
            self.sendMessage("接单报错，还有未处理的单子，立即通知管理员", driver.page_source)
            winsound.Beep(400, 900)
            sys.exit()

    # 抓取数据
    # def getAndSaveData(self, driver):
    #     self.log(driver.page_source)
    #     tempStr = driver.find_element(By.CLASS_NAME,"patientName___OCL9x").text
    #     tempStr.replace("(",",").replace(")","")
    #     tempStrs = tempStr.split(",")
    #     yaopinList = driver.find_elements(By.CSS_SELECTOR,".patientItem___1eOJR:nth-child(3)+div")
    #     gender = tempStrs[1]
    #     age = tempStrs[2]
    #     diagnosis = driver.find_elements(By.CLASS_NAME,"patientItem___1eOJR")[1].text
    #
    #
    #     name = driver.find_element
    #     dosageForm = driver.find_element().text
    #     usage = driver.find_element().text
    #     spec = driver.find_element().text
    #     # data = {
    #     #     "age": "18",
    #     #     "code": "Dx0002",
    #     #     "diagnosis": "幽门螺杆菌引起的胃炎",
    #     #     "dosageForm": "颗粒剂",
    #     #     "gender": "男",
    #     #     "name": "L-谷氨酰胺呱仑酸钠颗粒",
    #     #     "spec": "2.0mg*15袋/包",
    #     #     "usage": "口服"
    #     # }
    #     data = { }
    #     resp = requests.post(baseRefUrl+"/ouprescriptionitems/GetOuprescriptionitemList",data)
    #     resData = json.dumps(resp.content)
    #     if resData.status is "true" :
    #         self.log("添加数据成功")

    # 发送短信
    def sendMessage(self, content, html):
        self.log("=================" + content + "===================")
        self.saveLogAndHtml(html)
        content = ",登录名:" + str(self.username) + ",IP地址" + str(self.userIp) + ",报错内容:" + content
        ##### 上传
        files = {
            "files": (self.saveLogPath+'/'+self.current_time+"-error.txt", open(self.saveLogPath+'/'+self.current_time+"-error.txt", "rb"), "images/git")
        }
        requests.post(
            baseRefUrl + "/mailSettings/SetMailSettingOrEntryCodeFileUpload?entryCode=0001&content=" + content + "&type=0",
            files=files)
        self.log("发送短信成功")

    # log
    def log(self, message):
        try:
            print(str(message))
            folder = os.path.exists(self.saveLogPath)
            if not folder:
                os.makedirs(self.saveLogPath)
            log = open(self.saveLogPath+'/'+self.current_time+"-log.txt", "a", encoding="utf-8")
            log.write("==========打印的时间=" + str(datetime.now()) + "==========")
            log.write("\n")
            log.write(str(message))
            log.write("\n")
        except Exception:
            self.sendMessage("保存日志报错操作，立即通知管理员,message = 'log void error!'", self.driver.page_source)

    #  上传html和日志
    def saveLogAndHtml(self, html):
        folder = os.path.exists(self.saveLogPath)
        if not folder:
            os.makedirs(self.saveLogPath)
        errorFile = open(self.saveLogPath+'/'+self.current_time+"-error.txt", "w", encoding="utf-8")
        errorFile.write("==========前60行日志 start===========")
        logFile = open(self.saveLogPath+'/'+self.current_time+"-log.txt", "r", encoding="utf-8")
        errorFile.write("\n")
        logs = logFile.readlines()[-60:]
        for log in logs:
            errorFile.write(log)
        errorFile.write("\n")
        errorFile.write("==========前60行日志 end===========")
        errorFile.write("\n")
        errorFile.write("\n")
        errorFile.write(str(html))
        errorFile.close()

    # 电子狗
    def startEdog(self):
        tempFlag = 0
        index = 0
        # 2分钟，如果没变动 则
        while True:
            dogFlag = str(self.dogFlag)
            if tempFlag != dogFlag:
                tempFlag = dogFlag
                index = 0
            if index > 35 and tempFlag == dogFlag:
                winsound.Beep(400, 900)
                self.sendMessage("接单错误，可能还有未处理的单子，立即通知管理员,message = 'start e-dog void error!'", self.driver.page_source)
                #发送错误信息，尝试重启
                self.start()
                break
            if index > 25:
                self.log("重启计数，总35，目前："+str(index))
            index = index + 1
            time.sleep(4)
    pass


if __name__ == '__main__':
    DoctorAutomate("test").start()
